﻿using System;
using System.Reflection;
using System.Windows.Forms;
using Ion.MarketView.Ifc;
using log4net;
using System.Threading;
using Application = Ion.MarketView.Ifc.Application;
using System.Collections.Generic;

namespace SubscriberSheet
{
    class MkvEventHandler
    {
        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private readonly MkvSheet _mkvSheet;
        private static String _reqServiceName;
        private readonly ObserverCustom _myObserverCustom = new ObserverCustom();
        private readonly ObserverQuote _myObserverQuote = new ObserverQuote();
        private readonly IDictionary<String, String> _dataDict = new Dictionary<String, String>();
        private AutoResetEvent waitHandle = new AutoResetEvent(false);
        private Service _service;

        public MkvEventHandler(MkvSheet mkvSheet)
        {
            _mkvSheet = mkvSheet;                       
        }

        public void Initialize(object sender, EventArgs e)
        {
            SetControlPropertyThreadSafe(_mkvSheet.label1,"Text", "Initializing");
        }

        private delegate void SetControlPropertyThreadSafeDelegate(Control control, string propertyName, object propertyValue);

        public static void SetControlPropertyThreadSafe(Control control, string propertyName, object propertyValue)
        {
            if (control.InvokeRequired)
            {
                control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new[] { control, propertyName, propertyValue });
            }
            else
            {
                control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new[] { propertyValue });
            }
        }

        public void NewService(object sender, ServiceEventArgs args)
        {
            if (_reqServiceName.Equals(args.Service.ComponentName))
            {
                _service = args.Service;

                _myObserverQuote.Supply += HandleQuoteSupply;
                _service.SubscribeQuoteRecord("0_CCOL1U10", _myObserverQuote);

                Thread _dicTask = new Thread(new ThreadStart(ReadDictAndListenAll));
                _dicTask.Start();
            }
        }

        private void HandleDownloadCustomTable(object sender, DownloadExEventArgs args)
        {
            Log.Fatal("Downloading data dictionary for "+args.DownloadMode);
        }

        private void HandleSuppliedCustomTable(object sender, CustomRecordEventArgs args)
        {
            Log.Fatal("Custom record supplied " + args.Record);
        }

        private void HandleQuoteSupply(object sender, RecordEventArgs args)
        {
            foreach (FieldPair fv in args.Record.FieldPairs) {

                if(!_dataDict.ContainsKey(fv.Desc.Name))
                    _dataDict.Add(fv.Desc.Name, fv.Field.FieldType.Name);

                Log.Fatal(String.Format("Field Name {0}, Type {1}", fv.Desc.Name, fv.Field.FieldType.Name));

                if (fv.Field.FieldType.Name.Equals("Double") && fv.Field.IsValid)
                {
                    Log.Fatal(String.Format("TypeName {0}, Value {1}, FieldName {2} ",fv.Field.FieldType.Name , fv.Field.GetReal(), fv.Desc.Name));
                }
                else if (fv.Field.FieldType.Name.Equals("Intr32") && fv.Field.IsValid)
                {
                    Log.Fatal(String.Format("TypeName {0}, Value {1}, FieldName {2} ", fv.Field.FieldType.Name, fv.Field.GetInt(), fv.Desc.Name));
                } 
                else if (fv.Field.FieldType.Name.Equals("Boolean") && fv.Field.IsValid)
                {
                    Log.Fatal(String.Format("TypeName {0}, Value {1}, FieldName {2} ", fv.Field.FieldType.Name, fv.Field.GetBool(), fv.Desc.Name));
                }
                else if (fv.Field.FieldType.Name.Equals("String") && fv.Field.IsValid)
                {
                    Log.Fatal(String.Format("TypeName {0}, Value {1}, FieldName {2} ", fv.Field.FieldType.Name, fv.Field.GetString(), fv.Desc.Name));
                }
            }
            Log.Fatal("Quote record supplied " + args.Record);
           
            waitHandle.Set();
        }

        public void RegisteredIdle(object sender, EventArgs e)
        {
            SetControlPropertyThreadSafe(_mkvSheet.label1, "Text", "Registered Idle");
        }

        public void Registered(object sender, RegistrationResultEventArgs args)
        {
            SetControlPropertyThreadSafe(_mkvSheet.label1, "Text", "Registered");
        }

        public void PasswordChange(object sender, PasswordChangeEventArgs args)
        {
            SetControlPropertyThreadSafe(_mkvSheet.label1, "Text", "Password Changed");
        }

        public void Started(object sender, EventArgs e)
        {
            SetControlPropertyThreadSafe(_mkvSheet.label1, "Text", "Started");
            _reqServiceName = Application.Instance.MkvReadString("SERVICENAME", 0, "IFC_Pricing");
            SetControlPropertyThreadSafe(_mkvSheet.label4, "Text", _reqServiceName);
        }
        public void Stopped(object sender, EventArgs e)
        {   
            // When x is clicked app.Stop() is called but at the same time form component is disposed
            //TODO SetControlPropertyThreadSafe(_mkvSheet.label1, "Text", "Stopped");
        }

        void ReadDictAndListenAll()
        {
            waitHandle.WaitOne();
            Console.WriteLine("Ready to read dictinory and subscribe all");

            CustomRecordDefinition oCustomDefinition = CustomRecordDefinition.CreateNewDefinition("QUOTE", "QUOTE");

            foreach (String _fldName in _dataDict.Keys)
            {
                oCustomDefinition.AddCustomField(_fldName);                              
            }
            _mkvSheet.UpdateTable(_dataDict);
            _myObserverCustom.Supply += HandleSuppliedCustomTable;
            _myObserverCustom.DownloadEx += HandleDownloadCustomTable;

            _service.SubscribeCustomTable(oCustomDefinition, _myObserverCustom);            
        }
    }
}
